/*
 * HeaderPanel.java
 *
 */

package net.kernub.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MenuBar;

import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyCodes;

import net.kernub.client.wwwConstants;
import net.kernub.client.wwwMessages;

import net.kernub.client.core.RPC;
import net.kernub.client.core.RPCCallback;
import net.kernub.client.core.datatype.CBoolean;
import net.kernub.client.core.datatype.CString;
import net.kernub.client.core.datatype.CInteger;

import net.kernub.client.datatype.AuthGetInfo;

/*
 * HeaderPanel class
 */
public class HeaderPanel extends DockPanel
{
	private final String MAX_HEIGHT = "30px";
	private final String ELEMENT_HEIGHT = "26px";

	private final wwwConstants constants = GWT.create( wwwConstants.class );
	private final wwwMessages messages = GWT.create( wwwMessages.class );

	private final HorizontalPanel loadingPanel = new HorizontalPanel();

	private final HorizontalPanel westPanel = new HorizontalPanel();
	private final Label siteLabel = new Label(); //!< site name 
	private final Label infoLabel = new Label();
	private Timer infoTimer = null;

	private final FlexTable eastPanel = new FlexTable();
	//private final Label languageLabel = new Label(); //!< language select

	private final FlexTable authPanel = new FlexTable();
	private final TextBox usernameTextBox = new TextBox(); //!< username text box
	private final PasswordTextBox passwordTextBox = new PasswordTextBox(); //!< password text box

	private final FlexTable loggedInPanel = new FlexTable();
	private final Label loggedInLabel = new Label();
	private final Hyperlink authLink = new Hyperlink();
	private final Hyperlink logoutLink = new Hyperlink();

	public HeaderPanel()
	{
		createWestPanel();
		createCenterPanel();
		createEastPanel();

		// west panel: site name
		this.add( westPanel, DockPanel.WEST );
		this.setCellHorizontalAlignment( westPanel, DockPanel.ALIGN_LEFT );

		// center panel: temporary information
		this.add( infoLabel, DockPanel.CENTER );
		this.setCellHorizontalAlignment( infoLabel, DockPanel.ALIGN_CENTER );

		// auth + language menu
		this.add( eastPanel, DockPanel.EAST );
		this.setCellHorizontalAlignment( eastPanel, DockPanel.ALIGN_RIGHT );

		// general main panel
		this.setWidth( "100%" );
		this.setHeight( MAX_HEIGHT );
		this.addStyleName( "HeaderPanel" );
	}

	public Widget createWestPanel()
	{
		siteLabel.setText( constants.headerSiteTxt() );
		siteLabel.addStyleName( "Header_Common" );
		siteLabel.addStyleName( "Header_SiteLabel" );

		final Label visitorCountLabel = new Label();
		visitorCountLabel.addStyleName( "Header_Common" );
		visitorCountLabel.addStyleName( "Header_VisitorCountLabel" );

		final VerticalPanel siteHeaderPanel = new VerticalPanel();
		siteHeaderPanel.add( siteLabel );
		siteHeaderPanel.add( visitorCountLabel );
		siteHeaderPanel.setHeight( ELEMENT_HEIGHT );
		siteHeaderPanel.setCellHorizontalAlignment( visitorCountLabel, VerticalPanel.ALIGN_CENTER );

		final Image loadingImage = new Image( "images/loading.gif" );
		loadingImage.addStyleName( "Header_LoadingImage" );

		final Label loadingLabel = new Label( constants.loading() );
		loadingLabel.addStyleName( "Header_Common" );
		loadingLabel.addStyleName( "Header_LoadingText" );

		loadingPanel.add( loadingImage );
		loadingPanel.add( loadingLabel );

		westPanel.add( siteHeaderPanel );
		westPanel.add( loadingPanel );

		DeferredCommand.addCommand( new Command() {
			public void execute()
			{
				RPC.call( "core/Visitor", "getNumber", new RPCCallback<CInteger>() {
					public void onCallback( CInteger r )
					{
						String txt = r.get() + "";
						visitorCountLabel.setText( txt );
					}
				});
			}
		});

		return westPanel;
	}

	public Widget createCenterPanel()
	{
		infoLabel.setText( "" );
		infoLabel.setVisible( false );
		infoLabel.setHeight( ELEMENT_HEIGHT );
		infoLabel.addStyleName( "Header_Common" );
		infoLabel.addStyleName( "Header_InfoLabel" );
		return infoLabel;
	}

	public Widget createEastPanel()
	{
		createLoggedInPanel();
		createAuthPanel();

		// We can use i18n.client.LocaleInfo to get all available locale, locale friendly name...etc.
		final MenuBar languageSubMenu = new MenuBar( true );
		languageSubMenu.addStyleName( "Header_Common" );
		languageSubMenu.addItem( constants.englishLang(), new Command() {
			public void execute()
			{
				final String url = GWT.getHostPageBaseURL() + "www.php?locale=en";
				Window.open( url, "_self", "" );
			}
		});
		languageSubMenu.addItem( constants.frenchLang(), new Command() {
			public void execute()
			{
				final String url = GWT.getHostPageBaseURL() + "www.php?locale=fr";
				Window.open( url, "_self", "" );
			}
		});

		final MenuBar languageMenu = new MenuBar();
		languageMenu.addItem( constants.headerLanguageTxt(), languageSubMenu );
		languageMenu.addStyleName( "Header_Common" );
		languageMenu.addStyleName( "Header_LanguageList" );
		languageMenu.setAnimationEnabled( false );

		eastPanel.setWidget( 0, 0, loggedInPanel );
		eastPanel.setWidget( 0, 1, languageMenu );
		eastPanel.setCellPadding( 0 );
		eastPanel.setHeight( ELEMENT_HEIGHT );
		return eastPanel;
	}

	public Widget createLoggedInPanel()
	{
		//final Hyperlink authLink = new Hyperlink();
		authLink.setText( constants.authenticateTxt() );
		authLink.addStyleName( "Header_Common" );
		authLink.addStyleName( "LinkCursor" );
		authLink.addClickHandler( new ClickHandler() {
			public void onClick( ClickEvent event ) {
				eastPanel.setWidget( 0, 0, authPanel );
				usernameTextBox.setFocus( true );
			}
		});

		//final Hyperlink logoutLink = new Hyperlink();
		logoutLink.setText( constants.logoutTxt() );
		logoutLink.addStyleName( "Header_Common" );
		logoutLink.addStyleName( "LinkCursor" );
		logoutLink.addClickHandler( new ClickHandler() {
			public void onClick( ClickEvent event ) {
				RPC.call( "core/Auth", "logout", new RPCCallback<CBoolean>() {
					public void onCallback( CBoolean result ) {
						loggedInLabel.setText( "" );
						//loggedInPanel.setText( 0, 0, "" );
						loggedInPanel.setWidget( 0, 1, authLink );

						UIGlobals.instance().reset();
					}
				});
			}
		});

		loggedInLabel.setText( "" ); // later
		loggedInLabel.addStyleName( "Header_Common" );
		loggedInLabel.addStyleName( "Header_LoggedInLabel" );

		loggedInPanel.setWidget( 0, 0, loggedInLabel );
		loggedInPanel.setWidget( 0, 1, authLink );
		loggedInPanel.setCellPadding( 0 );
		loggedInPanel.setHeight( ELEMENT_HEIGHT );
		loggedInPanel.addStyleName( "Header_Common" );
		loggedInPanel.addStyleName( "Header_LoggedInPanel" );

		// retreive username
		// use a deferred command 'cause unable to execute RPC at init time...
		DeferredCommand.addCommand( new Command() {
			public void execute() {
				RPC.call( "site/Authenticate", "getInfo", new RPCCallback<AuthGetInfo>() {
					public void onCallback( AuthGetInfo r ) {

						UIGlobals.instance().set( r.UILabelManagable(), r.UILinkAddable(), r.UILinkEditable(), r.UILinkRemovable(), r.UIHomeEditable() );

						if( r.isAuthenticate() )
						{
							loggedInLabel.setText( messages.loggedInMsg(r.username()) );
							//loggedInPanel.setText( 0, 0, messages.loggedInMsg(result.username()) );
							loggedInPanel.setWidget( 0, 1, logoutLink );
						}
						else
						{
							loggedInLabel.setText( "" );
							//loggedInPanel.setText( 0, 0, "" );
							loggedInPanel.setWidget( 0, 1, authLink );
						}
					}
				});
			}
		});

		return loggedInPanel;
	}

	public Widget createAuthPanel()
	{
		final Button authButton = new Button( "ok" );
		authButton.setText( "Ok" );
		authButton.setHeight( "18px" );
		//authButton.addStyleName( "AuthButton" );
		//authButton.addStyleDependentName( "AuthButton" );
		authButton.addClickHandler( new ClickHandler() {
			public void onClick( ClickEvent event ) {
				RPC.call( "site/Authenticate", "authenticate", 
									usernameTextBox.getText(), passwordTextBox.getText(),
									new RPCCallback<AuthGetInfo>() {
					public void onCallback( AuthGetInfo result ) {
						onAuthenticated( result );
					}
				});
			}
		});

		final Label usernameLabel = new Label( constants.authUsernameTxt() );
		usernameLabel.addStyleName( "Header_Common" );

		final Label passwordLabel = new Label( constants.authPasswordTxt() );
		passwordLabel.addStyleName( "Header_Common" );

		usernameTextBox.setVisibleLength( 8 );
		usernameTextBox.setMaxLength( 64 );
		usernameTextBox.setHeight( "18px" );
		usernameTextBox.addStyleName( "Header_Common" );
		usernameTextBox.addStyleName( "Header_AuthTextBox" );
		usernameTextBox.addKeyPressHandler( new KeyPressHandler() {
			public void onKeyPress( KeyPressEvent event ) {
				if( event.getCharCode() == KeyCodes.KEY_ENTER ) {
					passwordTextBox.setFocus( true );
				}
			}
		});

		passwordTextBox.setVisibleLength( 8 );
		passwordTextBox.setMaxLength( 64 );
		passwordTextBox.setHeight( "18px" );
		passwordTextBox.addStyleName( "Header_Common" );
		passwordTextBox.addStyleName( "Header_AuthTextBox" );
		passwordTextBox.addKeyPressHandler( new KeyPressHandler() {
			public void onKeyPress( KeyPressEvent event ) {
				if( event.getCharCode() == KeyCodes.KEY_ENTER )
					authButton.click();
			}
		});

		final Hyperlink littleCross = new Hyperlink();
		littleCross.setText( "X" );
		littleCross.addStyleName( "LittleCross" );
		littleCross.addStyleName( "LinkCursor" );
		littleCross.addClickHandler( new ClickHandler() {
			public void onClick( ClickEvent event ) {
				// switch to loggedInPanel
				usernameTextBox.setText( "" );
				passwordTextBox.setText( "" );
				eastPanel.setWidget( 0, 0, loggedInPanel );
			}
		});

		authPanel.setWidget( 0, 0, usernameLabel );
		authPanel.setWidget( 0, 1, usernameTextBox );
		authPanel.setWidget( 0, 2, passwordLabel );
		authPanel.setWidget( 0, 3, passwordTextBox );
		authPanel.setWidget( 0, 4, authButton );
		authPanel.setWidget( 0, 5, littleCross );
		authPanel.setHeight( ELEMENT_HEIGHT );
		authPanel.addStyleName( "Header_Common" );
		authPanel.addStyleName( "Header_AuthPanel" );

		return authPanel;
	}

	private void onAuthenticated( AuthGetInfo r )
	{
		UIGlobals.instance().set( r.UILabelManagable(), r.UILinkAddable(), r.UILinkEditable(), r.UILinkRemovable(), r.UIHomeEditable() );

		if( r.isAuthenticate() )
		{
			loggedInLabel.setText( messages.loggedInMsg( r.username() ) );
			//loggedInPanel.setText( 0, 0, messages.loggedInMsg(usernameTextBox.getText()) );
			loggedInPanel.setWidget( 0, 1, logoutLink );
			usernameTextBox.setText( "" );
			passwordTextBox.setText( "" );

			// switch to loggedInPanel
			eastPanel.setWidget( 0, 0, loggedInPanel );
		}
		else
		{
			setTempInfo( constants.badAuthentication() );
			passwordTextBox.setText( "" );

			// switch to authPanel
			eastPanel.setWidget( 0, 0, loggedInPanel );
		}
	}

	public void setTempInfo( String text )
	{
		if( infoTimer != null )
		{
			infoTimer.cancel();
			infoTimer = null;
		}

		infoTimer = new Timer() {
			@Override
			public void run() {
				infoLabel.setVisible( false );
			}
		};
		
		infoLabel.setText( text );
		infoLabel.setVisible( true );

		infoTimer.schedule( 5000 );
	}

	public void showLoading()
	{
		loadingPanel.setVisible( true );
	}

	public void hideLoading()
	{
		loadingPanel.setVisible( false );
	}
}

